package org.web.accesscontrollist.server.biz.impl;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.web.accesscontrollist.sdk.biz.AclResourceDetailBiz;
import org.web.accesscontrollist.sdk.dto.*;
import org.web.accesscontrollist.sdk.dto.constant.AclResourceConstant;
import org.web.accesscontrollist.sdk.dto.query.QueryAclUserResourceBindingRequest;
import org.web.accesscontrollist.server.domain.AclResourceDefinitionDO;
import org.web.accesscontrollist.server.domain.AclResourceDetailDO;
import org.web.accesscontrollist.server.domain.query.QueryAclResourceDefinition;
import org.web.accesscontrollist.server.domain.query.QueryAclResourceDetail;
import org.web.accesscontrollist.server.service.AclResourceDefinitionService;
import org.web.accesscontrollist.server.service.AclResourceDetailService;
import org.web.base.domain.ResultDO;
import org.web.base.domain.helper.ResultHelper;
import org.web.base.domain.helper.ServiceExceptionHelper;
import org.web.base.domain.helper.ValidationHelper;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service("aclResourceDetailBiz")
public class AclResourceDetailBizImpl implements AclResourceDetailBiz, AclResourceConstant {

    private static final Logger logger = Logger.getLogger(AclResourceDetailBizImpl.class);


    @Resource
    AclResourceDetailService aclResourceDetailService;

    @Resource
    private AclBusinessLineServiceBiz aclBusinessLineServiceBiz;

    @Resource
    private AclResourceDefinitionService aclResourceDefinitionService;

    @Override
    public ResultDO<List<AclResourceDetailDTO>> saveAclResourceDetailBatch(SaveAclResourceDetailBatchDTO saveAclResourceDetailBatchDTO) {
        ResultDO<List<AclResourceDetailDTO>> resultDO = new ResultDO<>();
        try {
            AclResourceHelper.checkSaveAclDetailBatchDTO(saveAclResourceDetailBatchDTO);
            resultDO.setDomain(saveAclResourceDetailBatchDTO.getAclResourceDetailDTOList());
            DefaultAclResourceDefinition defaultAclResourceDefinitionDTO = saveAclResourceDetailBatchDTO.getDefaultAclResourceDefinitionDTO();
            OperatorDTO operatorDTO = defaultAclResourceDefinitionDTO.getOperatorDTO();

            // 判断业务线businessLine是否存在。 校验业务线是否存在，如果存在，则校验权限； 如果不存在，则构建缺省业务线。
            aclBusinessLineServiceBiz.judgeOperatorOrBuildDefaultBusinessLine(operatorDTO);

            //有优化空间，逻辑唯一判断，不需要逐条查询。可以根据BusinessLine一次性取出，转成MAP，在逐条处理过程中，从map中判断记录是否在DB存在, 减少DB访问次数。
            for (AclResourceDetailDTO aclResourceDetailDTO : saveAclResourceDetailBatchDTO.getAclResourceDetailDTOList()) {
                // 逻辑唯一，从数据库找到记录，如果存在，则进行修改，不存在，则进行新增操作。
                QueryAclResourceDetail queryAclResourceDetail = new QueryAclResourceDetail();
                queryAclResourceDetail.setBusinessLine(aclResourceDetailDTO.getBusinessLine());
                queryAclResourceDetail.setDefinitionName(queryAclResourceDetail.getDefinitionName());
                queryAclResourceDetail.setDetailName(aclResourceDetailDTO.getDetailName());

                AclResourceDetailDO aclResourceDetailDOFromDB = aclResourceDetailService.selectOneAclResourceDetail(queryAclResourceDetail);
                if (aclResourceDetailDOFromDB != null) {
                    AclResourceDetailDO updateAclResourceDetailDO = new AclResourceDetailDO();
                    BeanUtils.copyProperties(updateAclResourceDetailDO, aclResourceDetailDTO);
                    aclResourceDetailDTO.setAclResourceDetailId(aclResourceDetailDOFromDB.getAclResourceDetailId());
                    aclResourceDetailDTO.setAclResourceDefinitionId(aclResourceDetailDOFromDB.getAclResourceDefinitionId());
                    updateAclResourceDetailDO.setAclResourceDetailId(aclResourceDetailDOFromDB.getAclResourceDetailId());
                    Date current = new Date();
                    updateAclResourceDetailDO.setCreateTime(null);
                    updateAclResourceDetailDO.setUpdateTime(current);
                    aclResourceDetailService.updateAclResourceDetailByAclResourceDetailId(updateAclResourceDetailDO);
                    aclResourceDetailDTO.setCreateTime(updateAclResourceDetailDO.getCreateTime());
                    aclResourceDetailDTO.setUpdateTime(updateAclResourceDetailDO.getUpdateTime());
                } else {
                    // 新增的场合，需要校验resourceDefinition是否存在。并且绑定definition_id
                    AclResourceDetailDO insertAclResourceDetailDO = new AclResourceDetailDO();
                    // 不要改变copyProperties位置。
                    BeanUtils.copyProperties(insertAclResourceDetailDO, aclResourceDetailDTO);
                    // 针对新增记录，先判断definition的关联性。
                    QueryAclResourceDefinition queryAclResourceDefinition = new QueryAclResourceDefinition();
                    queryAclResourceDefinition.setBusinessLine(aclResourceDetailDTO.getBusinessLine());
                    queryAclResourceDefinition.setDefinitionName(aclResourceDetailDTO.getDefinitionName());
                    AclResourceDefinitionDO aclResourceDefinitionDOFromDB = aclResourceDefinitionService.selectOneAclResourceDefinition(queryAclResourceDefinition);
                    Date current = new Date();
                    if (ObjectUtils.isEmpty(aclResourceDefinitionDOFromDB)) {
                        // resourceDefinition 不存在的场合，缺省构建一条记录。
                        AclResourceDefinitionDO insertAclResourceDefinitionDO = new AclResourceDefinitionDO();
                        BeanUtils.copyProperties(insertAclResourceDefinitionDO, defaultAclResourceDefinitionDTO);
                        insertAclResourceDefinitionDO.setAclResourceDefinitionId(aclResourceDefinitionDOFromDB.getAclResourceDefinitionId());
                        insertAclResourceDefinitionDO.setDefinitionName(aclResourceDetailDTO.getDefinitionName());
                        insertAclResourceDefinitionDO.setCreateTime(current);
                        insertAclResourceDefinitionDO.setUpdateTime(current);
                        aclResourceDefinitionService.insertAclResourceDefinition(insertAclResourceDefinitionDO);
                        aclResourceDetailDTO.setAclResourceDefinitionId(insertAclResourceDefinitionDO.getAclResourceDefinitionId());
                    } else {
                        insertAclResourceDetailDO.setAclResourceDefinitionId(aclResourceDefinitionDOFromDB.getAclResourceDefinitionId());
                    }
                    insertAclResourceDetailDO.setCreateTime(current);
                    insertAclResourceDetailDO.setUpdateTime(current);
                    aclResourceDetailService.insertAclResourceDetail(insertAclResourceDetailDO);
                    aclResourceDetailDTO.setCreateTime(insertAclResourceDetailDO.getCreateTime());
                    aclResourceDetailDTO.setUpdateTime(insertAclResourceDetailDO.getUpdateTime());
                }
                aclResourceDetailDTO.setExecuteSuccess(true);
            }
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e, saveAclResourceDetailBatchDTO.getAclResourceDetailDTOList());
        }
        return resultDO;
    }

    @Override
    public ResultDO<List<AclResourceDetailDTO>> selectAclResourceDetailList(QueryAclUserResourceBindingRequest queryAclUserResourceBindingRequest) {
        ResultDO<List<AclResourceDetailDTO>> resultDO;
        try {
            ValidationHelper.validateAndThrow(QueryAclUserResourceBindingRequest.class, queryAclUserResourceBindingRequest);
            QueryAclResourceDetail queryAclResourceDetail = new QueryAclResourceDetail();
            BeanUtils.copyProperties(queryAclResourceDetail, queryAclUserResourceBindingRequest);
            ResultDO<List<AclResourceDetailDO>> selectAclResourceDetailListResult = aclResourceDetailService.selectAclResourceDetailListResult(queryAclResourceDetail);
            resultDO = ResultHelper.buildResultDOByResultDO(selectAclResourceDetailListResult, AclResourceDetailDTO.class);
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }

    @Override
    public ResultDO<List<String>> selectDistinctAclResourceDetail(QueryAclUserResourceBindingRequest queryAclUserResourceBindingRequest) {
        ResultDO<List<String>> resultDO = new ResultDO<>();
        try {
            ValidationHelper.validateAndThrow(QueryAclUserResourceBindingRequest.class, queryAclUserResourceBindingRequest);
            QueryAclResourceDetail queryAclResourceDetail = new QueryAclResourceDetail();
            BeanUtils.copyProperties(queryAclResourceDetail, queryAclUserResourceBindingRequest);
            List<String> selectDistinctList = aclResourceDetailService.selectDistinctList(queryAclResourceDetail);
            resultDO.setDomain(selectDistinctList);
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }


}
